#pragma once

#include "dog.h"
#include "bird.h"
#include "fish.h"

namespace zoo
{
    using visitor_token_set1 = visitor_token_set<dog, bird>;
    using visitor_token_set2 = visitor_token_set<fish>;

    struct visitor1 : public visitor_token_set1
    {
        static const visitor1* instance()
        {
            static visitor1 g;
            return &g;
        }

        void visit(dog* d) const override
        {
            d->swim();
        }

        void visit(dog* d, int i) const override
        {
            d->swim();
        }

        void visit(bird* b) const override
        {
            b->fly();
        }

        void visit(bird* b, int i) const override
        {
            b->fly();
        }
    };

    struct visitor2 : public visitor_token_set2
    {
        static const visitor2* instance()
        {
            static visitor2 g;
            return &g;
        }

        void visit(fish* f) const override
        {
            f->dive();
        }

        void visit(fish* f, int i) const override
        {
            f->dive();
        }
    };
}; // !namespace zoo
